package cn.nexd.app.collector.presenter.map;

import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.text.TextUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.nexd.app.collector.Configuration;
import cn.nexd.app.collector.Thread.RecordThread;
import cn.nexd.app.collector.application.NexdApplication;
import cn.nexd.app.collector.model.FloorLayer;
import cn.nexd.app.collector.util.UMengUtil;
import cn.nexd.sdk.location.NexdIndoorLocation;
import cn.nexd.sdk.location.NexdIndoorLocationAgent;
import cn.nexd.sdk.location.NexdIndoorLocationConfiguration;
import cn.nexd.sdk.location.NexdIndoorLocationListener;
import cn.nexd.sdk.location.NexdIndoorLocationResult;
import cn.nexd.sdk.location.bean.IndoorLocationResultRecordBean;
import cn.nexd.sdk.location.core.DefaultIndoorLocationResultRecordListener;
import cn.nexd.utils.framework.error.NexdCrashException;
import cn.nexd.utils.framework.tools.FileUtil;
import cn.nexd.utils.framework.tools.Logger;
import cn.nexd.utils.framework.tools.StringUtil;

/**
 * 地图定位测试类
 * <p>
 * 用来进行相关定位测试，展示相应地图信息，楼层信息，根据定位结果，回调 UI 刷新数据， 记录定位时的所有数据。
 * <p>
 * Created by wangxu on 16/10/26.
 */

public class NexdMapPresenter implements NexdMapContract.Presenter, NexdIndoorLocationListener {


    private static final String TAG = "NexdMapPresenter";

    private NexdMapContract.View view;

    private Context context;
    private NexdIndoorLocationAgent indoorLocationAgent;
    private NexdIndoorLocationConfiguration.Buidler buidler;

    private long buildingId = -1L;
    private long floorId = -1L;

    private boolean isNotified = false;

    private Map<Long, String> floorLayerMap;
    private List<String> itemNames = null;

//    private static final List<List<IndoorLocationResultRecordBean>> queue = new ArrayList<>();

    private RecordThread recordThread;

    public NexdMapPresenter(NexdMapContract.View view, Context context) {
        this.view = view;
        this.context = context;
        recordThread = RecordThread.getRecordThread();
        recordThread.setContext(context);
        recordThread.start();
    }

    @Override
    public List<String> initSelectItems(List<FloorLayer> floorLayers) {
        if (floorLayers != null && floorLayers.size() != 0) {
            itemNames = new ArrayList<>();
            floorLayerMap = new HashMap<>();
            for (FloorLayer floorLayer : floorLayers) {
                floorLayerMap.put(floorLayer.getFloorId(), floorLayer.getFloorName());
                itemNames.add(floorLayer.getFloorName());
            }
        }
        return itemNames;
    }

    @Override
    public void loadMap(long floorId) {
        this.floorId = floorId;
        if (!checkFloor(getSVGPath(floorId))) {
            view.showToast("参数异常，无法找到地图文件，请检查参数！");
            return;
        }
        view.loadMap(getSVGPath(floorId));
    }

    private String getSVGPath(long floorId) {
        return Configuration.getSavePath(Configuration.Path.LOCATION_BASE_PATH) + buildingId + "/" + floorId + ".svg";
    }


    @Override
    public void initLocation(String locationType, int locationInterval, final long buildingId, final int buffer) {


        Logger.debug(TAG, "" +
                "初始化定位: \n" +
                "locationType = " + locationType + "\n" +
                "locationInterval = " + locationInterval + "\n" +
                "buildingId = " + buildingId + "\n" +
                "buffer = " + buffer);

        // buffer 目前只针对蓝牙进行设计， WiFi 定位时， 不使用缓存机制

        this.buildingId = buildingId;
        indoorLocationAgent = NexdIndoorLocationAgent.getIndoorLocationAgent(context);
        buidler = new NexdIndoorLocationConfiguration.Buidler();
        buidler.setLocationRate(locationInterval == 0 ? 1000 : locationInterval)
                .setAppkey("")
                .setDebugMode(true);
        if ("wifi".equals(locationType)) {
            buidler.setLocationMode(NexdIndoorLocation.LocationMode.LOCATION_MODE_WIFI_ONLY).
                    setWifiCollectorRate(500)
                    .setWifiResultCacheTime(5000);
        } else if ("blue".equals(locationType)) {
            buidler.setLocationMode(NexdIndoorLocation.LocationMode.LOCATION_MODE_BEACON_ONLY)
                    .setBeaconCollectorRate(500)
                    .setBeaconResultCacheTime(buffer);
        } else {
            buidler.setLocationMode(NexdIndoorLocation.LocationMode.LOCATION_MODE_MIX);
        }


        indoorLocationAgent.setIndoorLocationResultRecordListener(new DefaultIndoorLocationResultRecordListener() {
            @Override
            public void callback(List<IndoorLocationResultRecordBean> list) {

                recordThread.add(new ArrayList<>(list));
            }
        });
        // 将定位 mall 记录到记录中，以便后续分表读取数据
        NexdApplication.getInstance().getSqlHelper().getDb().execSQL("insert or ignore into mall (mallId) values (" + buildingId + ")");
    }


    private boolean checkFloor(String path) {
        if (TextUtils.isEmpty(path)) {
            return false;
        }

        try {
            if (!FileUtil.checkExist(path)) {
                return false;
            }
        } catch (IOException e) {
            UMengUtil.getInstance().reportError(context, e);
            NexdCrashException.getInstance().reportException(e);

            return false;
        }
        return true;
    }

    @Override
    public void changeFloor(long floorId) {
        stopLocation();
        if (!checkFloor(getSVGPath(floorId))) {
            view.showToast("参数异常，无法找到 " + floorId + "地图文件，请检查参数！");
            return;
        }
        view.changeFloor(getSVGPath(floorId), itemNames.indexOf(floorLayerMap.get(floorId)));
        this.floorId = floorId;
    }

    @Override
    public void startLocation(boolean autoChange) {

        if (autoChange) {
            Logger.debug(TAG, "startLocation: 切层定位");
            indoorLocationAgent.startLocation(buildingId, this, buidler.build());
        } else {
            Logger.debug(TAG, "startLocation: 非切层定位");
            indoorLocationAgent.startLocation(buildingId, floorId, this, buidler.build());
        }
    }


    private void record(List<IndoorLocationResultRecordBean> list) {
        if (!NexdApplication.getInstance().getSqlHelper().tableIsExist("mall_" + list.get(0).getBuildingId())) {
            NexdApplication.getInstance().getSqlHelper().getDb().execSQL("create table mall_" + list.get(0).getBuildingId() + "(mallId, floorId ,position, signal, date)");
        }
        for (IndoorLocationResultRecordBean indoorLocationResultRecordBean : list) {
            ContentValues value = new ContentValues();
            value.put("mallId", indoorLocationResultRecordBean.getBuildingId());
            value.put("floorId", indoorLocationResultRecordBean.getFloorId());
            value.put("position", indoorLocationResultRecordBean.getIndoorLocationResult());
            value.put("signal", StringUtil.compress(indoorLocationResultRecordBean.getIndoorLocationDataList()));
            value.put("date", indoorLocationResultRecordBean.getDate());
            NexdApplication.getInstance().getSqlHelper().insertIfNotExist("mall_" + buildingId, value);
        }
    }

    @Override
    public void stopLocation() {
        if (indoorLocationAgent != null) {
            indoorLocationAgent.stopLocation();
        }
    }

    @Override
    public void destroyLocation() {
        if (indoorLocationAgent != null) {
            indoorLocationAgent.destroyLocation();
        }
    }

    @Override
    public void init() {

    }


    private void notifyChangeFloor(final long floorId) {
        stopLocation();
        ((Activity) context).runOnUiThread(new Runnable() {
            @Override
            public void run() {
                view.notifyChangeFloor(floorLayerMap.get(floorId), floorId, itemNames.indexOf(floorLayerMap.get(floorId)));
            }
        });
    }

    @Override
    public void onLocationStart() {
        Logger.debug(TAG, "开始采集!");
    }

    @Override
    public void onLocationChanged(NexdIndoorLocation nexdIndoorLocation, final NexdIndoorLocationResult nexdIndoorLocationResult) {
        if (nexdIndoorLocation.getLocationEngineState() == NexdIndoorLocation.LocationEngineState.ERROR_CODE_LOCATION_SUCCESS) {
            if (nexdIndoorLocationResult != null) {

                Logger.debug(TAG, "onLocationChanged:  \n current floor = " + floorId + "\n location floor = " + nexdIndoorLocationResult.getIndoorFloorId());
                if (nexdIndoorLocationResult.getIndoorFloorId() == floorId) {
                    view.updateLocationPoint(nexdIndoorLocationResult);
                } else {
                    if (isNotified) {
                        ((Activity) context).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                changeFloor(nexdIndoorLocationResult.getIndoorFloorId());
                            }
                        });
                    } else {
                        notifyChangeFloor(nexdIndoorLocationResult.getIndoorFloorId());
                        isNotified = true;
                    }
                }

            }
        } else {

            switch (nexdIndoorLocation.getLocationEngineState()) {
                case ERROR_CODE_LOCATION_ENGINE_ERROR:
                    view.showToast("定位引擎异常");
                    break;

                case ERROR_CODE_COLLECTOR_ERROR:
                    view.showToast("采集异常");
                    break;

                case ERROR_CODE_FAILURE_UNKNOWN_ERROR:
                    view.showToast("未知错误");
                    break;

                case ERROR_CODE_NOT_FOUND_LOCATION_CONFIG:
                    view.showToast("未找到定位配置文件");
                    break;

                default:
                    view.showToast("不知道发生了什么");
                    break;
            }
            stopLocation();
        }
    }
}
